package com.android.support.lib.universal.utils;

import android.util.Log;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * JSON数据转实体类工具，一般都是读取json数据。而转化为json数据的，比较少用。
 * 转化为json数据，只要实例化JSONObject,调用put方法即可。
 * Created by 彭治铭 on 2017/5/26.
 */

public class UtilJSONObject<T> {
    private static UtilJSONObject utilJSONObject;

    private UtilJSONObject() {
    }

    public static UtilJSONObject getInstance() {
        if (utilJSONObject == null) {
            utilJSONObject = new UtilJSONObject();
        }
        return utilJSONObject;
    }

    /**
     * JSONObject对象转实体类【通过反射实现，亲测可行，实体类只要不混淆即可，签名打包都没问题。效果杠杠的】
     *
     * @param jsonObject org.json.JSONObject 安卓自带的json对象，非第三方
     * @param clazz      泛型，Class类型。实体类的所有属性都必须是String类型。且必须具体空构造函数和set方法。【get方法里面没有用到，所以不需要】
     * @return 返回实体类
     */
    public T getBean(JSONObject jsonObject, Class<T> clazz) {
        T t = null;
        try {
            t = clazz.newInstance();//泛型实例化,注意啦，这一步，必须具备空构造函数，不然无法实例化
            //遍历类 成员属性【只对当前类有效，父类无效，即只获取本类的属性】
            Field[] fields = t.getClass().getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                // 获取属性的名字
                String name = fields[i].getName();
                //Log.e("test", "属性名称:\t" + name);
                String jName = name;
                // 将属性的首字符大写，方便构造get，set方法
                name = name.substring(0, 1).toUpperCase() + name.substring(1);
                // 获取属性的类型
                String type = fields[i].getGenericType().toString();
                // 如果type是类类型，则前面包含"class "，后面跟类名
                if (type.equals("class java.lang.String")) {
                    //Method m = t.getClass().getMethod("get" + name);
                    // 调用getter方法获取属性值
                    //String value = (String) m.invoke(t);
                    //调用set方法
                    Class[] parameterTypes = new Class[1];
                    parameterTypes[0] = fields[i].getType();
                    Method m = t.getClass().getMethod("set" + name, parameterTypes);
                    Object[] objects = new Object[1];
                    objects[0] = jsonObject.getString(jName);
                    m.invoke(t, objects);
                }
            }
        } catch (Exception e) {
            Log.e("test", "UtilJSONObject反射异常:\t" + e.getMessage());
        }
        return t;
    }

    /**
     * JSONObject转ArrayList
     *
     * @param jsonArray org.json.JSONArray安卓自带json数组
     * @param clazz     泛型，Class类型。
     * @return 返回 ArrayList 数组
     */
    public List<T> getArrayList(JSONArray jsonArray, Class<T> clazz) {
        List<T> list = new ArrayList<>();
        try {
            for (int i = 0; i < jsonArray.length(); i++) {
                list.add(getBean(jsonArray.getJSONObject(i), clazz));
            }
        } catch (Exception e) {
            Log.e("test", "UtilJSONObject反射List异常:\t" + e.getMessage());
        }
        return list;
    }
}
